import { Body, Controller, Post, UsePipes } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AdminHostController } from 'src/modules/HostController';
import dtoValidationPipe from 'src/pipe/Dto.pipe';
import { RedisService } from 'src/redis/redis.service';
import { errorReturn } from 'src/utils';
import { XjwtService } from 'src/xjwt/xjwt.service';
import { AdminService } from './admin.service';
import LoginDto from './dto/login.dto';

const dayjs = require('dayjs')

@Controller('admin')
@AdminHostController()
export class AdminController {
    constructor(
        private adminService:AdminService,
        private redisService:RedisService,
        private configService:ConfigService,
        private xjwtService:XjwtService
    ) {

    }

    @Post('login')
    @UsePipes(dtoValidationPipe())
    async login(@Body() {account, password}:LoginDto) {
        
        let loginCountKey = 'admin:lg:er:' + account + ':' + dayjs().format('YYMD') //登录错误次数
        const loginFailMaxCount = this.configService.get<number>('admin.loginFailMacCount') //最大失败登录次数

        const loginCount = Number(await this.redisService.get(loginCountKey))

        if(loginCount && loginCount >= loginFailMaxCount) {
            return errorReturn(`今天登录失败次数超过${loginFailMaxCount}次，禁止今天再登录`)
        }


        //加锁
        const lockKey = 'admin:lg:' + account
        const lock = await this.redisService.store.set(lockKey, '', {
            NX : true,
            EX : 10
        })
        if(!lock) return errorReturn('请稍后重试~')

        let time = dayjs().unix()
        let nextDayTime = dayjs(dayjs().format('YYYY-MM-DD')).add(1, 'day').unix() //下一天整点

        const adminUser = await this.adminService.validate(account, password)
        if(!adminUser) {
            this.redisService.store.del(lockKey)
            this.redisService.set(loginCountKey, loginCount + 1, {EX : nextDayTime - time})

            return errorReturn('登录账号或密码错误')
        }

        this.adminService.updateLogin(adminUser.adminId, time)

        return this.makeToken(adminUser.adminId, null, time)
    }

    @Post('refreshLogin')
    refreshLogin(@Body('token') token : string, adminId:number) {
        if(!token) return errorReturn()
        const jwtConfig = this.configService.get('admin.jwt')

        const res = this.xjwtService.verify(token, {
            secret : jwtConfig.refreshLogin.secret
        })

        if(!res) return errorReturn()
        const key = (res.key + jwtConfig.refreshLogin.scale) / jwtConfig.refreshLogin.scale
        if(key != adminId) return null

        return this.makeToken(adminId, jwtConfig)
    }

    private makeToken(adminId:number, jwtConfig?:any, time?:number) {
        if(!jwtConfig) {
            jwtConfig = this.configService.get('admin.jwt')
        }

        if(!time) {
            time = dayjs().unix()
        }
        
        let accessToken = this.xjwtService.sign({key : adminId * jwtConfig.login.scale + jwtConfig.login.scale, id : Math.ceil((time - 1030) / 263), time : time}, {
            secret : jwtConfig.login.secret,
            expiresIn : jwtConfig.expire
        })

        let refreshToken = this.xjwtService.sign({key : adminId * jwtConfig.refreshLogin.scale - jwtConfig.refreshLogin.scale, rid : Math.ceil((time - 8030) / 463), time : time}, {
            secret : jwtConfig.refreshLogin.secret,
            expiresIn : jwtConfig.expire
        })



        return {
            accessToken,
            refreshToken,
            expire : jwtConfig.expire
        }

    }
}